package org.dh2580.delay.queue.bean.db;

import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.apache.commons.beanutils.BeanUtils;
import org.dh2580.delay.queue.bean.model.EnumConvert;

/**
 * @Author: hao.deng
 * @Date: 2019/5/14-下午7:22
 */
public final class DBUtil {

    private static DataSource dataSource;

    public static void setDataSource(DataSource dataSource) {
        if (DBUtil.dataSource == null) {
            synchronized (DBUtil.class) {
                if (DBUtil.dataSource == null) {
                    DBUtil.dataSource = dataSource;
                }
            }
        }
    }

    public static <T> List<T> query(String sql, Class<T> clazz, Object... params) throws SQLException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException {
        Connection conn = null;
        PreparedStatement statement = null;

        try {
            conn = dataSource.getConnection();

            statement = conn.prepareStatement(sql);

            int index = 1;
            for (Object param : params) {
                statement.setObject(index++, param);
            }

            ResultSet resultSet = statement.executeQuery();

            ResultSetMetaData metaData = resultSet.getMetaData();
            int columCount = metaData.getColumnCount();

            List<T> rets = new ArrayList<>(32);

            while (resultSet.next()) {
                T t = clazz.newInstance();

                for (int i = 0; i < columCount; i++) {
                    String column = metaData.getColumnLabel(i + 1);
                    Object value = resultSet.getObject(column);

                    if (!clazz.getDeclaredField(column).getType().isEnum()) {
                        BeanUtils.setProperty(t, column, value);
                    } else {
                        Class fileClazz = clazz.getDeclaredField(column).getType();
                        Class[] interfaces = fileClazz.getInterfaces();

                        for (Class Interface : interfaces) {
                            if (Interface == EnumConvert.class) {
                                Object enumVal = ((EnumConvert) (fileClazz.getEnumConstants()[0])).convertToEnum(value);
                                BeanUtils.setProperty(t, column, enumVal);
                                break;
                            }
                        }
                    }


                }

                rets.add(t);
            }

            return rets;

        } finally {
            if (statement != null) {
                statement.close();
            }

            if (conn != null) {
                conn.close();
            }
        }

    }

    public static int execute(String sql, Object... params) throws SQLException {
        Connection conn = null;
        PreparedStatement statement = null;

        try {
            conn = dataSource.getConnection();

            statement = conn.prepareStatement(sql);

            int index = 1;
            for (Object param : params) {
                statement.setObject(index++, param);
            }

            return statement.executeUpdate();

        } finally {

            if (statement != null) {
                statement.close();
            }

            if (conn != null) {
                conn.close();
            }
        }

    }
}
